﻿#ifndef ECOLORCOMBOBOX_H
#define ECOLORCOMBOBOX_H

#include <QColor>
#include "EComboBox.h"
#include "API_BaseWidget.h"

/**
 * @brief 颜色选择复合框
 *
 * 颜色选择复合框为用户提供了一种方便选择预定义颜色的方法，同时也可以打开颜
 * 色选择对话框选择任意颜色。
 *
 * @note 由于基类QComboBox的clear方法不是虚函数，因此无法重载。如果在颜色对
 *       话框激活的情况下使用了clear方法清除复合框内的内容，则打开颜色对话框
 *       的项也会被清除，必须重新激活颜色对话框项。如果需要清除内容，必须使
 *       用本类提供的方法clearAllColors()。
 */
namespace BaseWidget
{
    class API_BASEWIDGET EColorComboBox : public EComboBox
    {
        Q_OBJECT
            Q_PROPERTY(bool colorDialogEnabled READ colorDialogEnabled WRITE enableColorDialog)
    public:

        /// @brief 构造函数。构造一个颜色选择复合框对象。
        /// @param parent 父窗口指针
        EColorComboBox(QWidget* parent = nullptr);

        /// @brief 获取当前选择的颜色
        /// @return 当前选择的颜色
        QColor currentColor() const;

        /// @brief 获取索引index指定的颜色。如果索引无效，则返回无效的颜色
        /// @param index 要获取的颜色的索引
        /// @return 获取的颜色
        QColor getColor(int index) const;

        /// @brief 检查是否使用颜色选择对话框
        /// @return 如果使用颜色选择对话框则返回true，否则返回false
        bool colorDialogEnabled() const;

        /// @brief 获取适合显示本控件的尺寸
        /// @return 适合显示本控件的尺寸
        QSize sizeHint() const;

        /// @brief 检查一种颜色是否已经在本控件中了
        /// @param color 要检查的颜色
        /// @return 如果在，返回true，否则返回false
        bool hasColor(const QColor& color);

        /// @brief 增加其它颜色
        void appendOtherColor();

        /// @brief 设置是否显示
        /// @param isShow 
        void setShowColorName(bool isShow);

    public slots:

        /// @brief 清除列表内的所有颜色，与clear方法不同，该方法不清除颜色对话框项
        void clearAllColors();

        /// @brief 在列表末尾添加一种颜色。如果这种颜色已经在列表内了，则直接返回
        /// @param c 要添加的颜色
        /// @param name 要添加的颜色的描述
        void appendColor(const QColor& color, const QString& name = QString());

        /// @brief 在列表指定位置添加一种颜色。如果这种颜色已经在列表内了，则直接返回。如果要添加的位置不存在，则在列表末尾添加
        /// @param c 要添加的颜色
        /// @param name 要添加的颜色的描述
        /// @param index 要添加颜色的位置
        void insertColor(const QColor& color, const QString& name = QString(), int index = -1);

        /// @brief 在当前列表的末尾添加预定义的颜色
        void appendPredefinedColors();

        /// @brief 在当前列表的末尾添加背景色的颜色
        void appendBackgroundColors();

        /// @brief 更新其它颜色
        /// @param color 其它颜色
        void updateOtherColor(const QColor& color);

        /// @brief 设置是否使用颜色选择对话框。如果使用颜色选择对话框，会在列表的最后添加一项启动颜色选择对话框的项
        /// @param enabled 如果为true则使用颜色选择对话框，否则不使用
        void enableColorDialog(bool enabled = true);

        /// @brief 设置当前选择的颜色。如果这种颜色不在列表内，则直接返回
        /// @param color 要设置为当前选择的颜色
        void setCurrentColor(const QColor& color);

    signals:

        /// @brief 当某种颜色被选中时发送这个信号
        /// @param color 被选中的颜色
        void activated(const QColor& color);

        /// @brief 当列表打开并且高亮显示某一种颜色时发送这个信号
        /// @param color 被高亮显示的颜色
        void highlighted(const QColor& color);

    private slots:

        /// @brief 激活索引对应的颜色
        /// @param index 索引
        void emitActivatedColor(int index);

        /// @brief 高亮索引对应的颜色
        /// @param index 索引
        void emitHighlightedColor(int index);

    private:
        bool m_colorDialogEnabled;
        QColor m_lastActivated;
        /// @brief 是否显示颜色的名字
        bool m_showColorName{ true };
    };
}
#endif

